#pragma once
#include <functional>
#include "Socket.h"
#include "InetAddress.h"
#include "Channel.h"
#include "EventLoop.h"
#include "Buffer.h"
#include "Timestamp.h"
#include <memory>
#include <atomic>

class EventLoop;
class Channel;
class Connection;
using spConnection = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection>
{
private:
    EventLoop* loop_;           //Acceptor对应的事件循环，在构造函数中传入
    std::unique_ptr <Socket> client_sock_;          //服务端用于监听的socket，在构造函数中创建
    std::unique_ptr<Channel> client_Channel_;    //Acceptor对应的channel，在构造函数中创建
    Buffer input_buffer_;         //接收缓存区
    Buffer output_buffer_;        //发送缓存区      
    std::atomic_bool disconnect_;   //客户端连接是否已断开，如果已断开，设为true

    std::function<void(spConnection)> close_CallBack;    //关闭fd_的回调函数，将回调TcpServer::close_Connection(Connection* conn)
    std::function<void(spConnection)> error_CallBack;     //fd_发生错误的回调函数，将回调TcpServer::error_Connection(Connection* conn)
    std::function<void(spConnection, std::string&)> on_Message_CallBack;     //处理报文的回调函数，将回调TcpServer::on_Message(Connection* conn)
    std::function<void(spConnection)> send_Complete_CallBack;               //发送数据完成后的回调函数,将回调TcpServer::sendComplete(Connection* conn)
    Timestamp lasttime_;    //时间戳，创建Connection对象为当前时间，每接收到一个报文，把时间戳更新为当前时间

public:
    Connection(EventLoop* loop, std::unique_ptr <Socket> clientSock);
    ~Connection();

    int fd() const;             //返回fd_成员
    std::string ip() const;     //返回ip地址
    uint16_t port() const;      //返回端口

    void on_Message();          //处理对端发来的消息
    void closeCallback();       //TCP连接关闭(断开)的回调函数，供Channel回调
    void errorCallback();       //TCP连接错误的回调函数，供Channel回调
    void writeCallback();        //处理写事件的回调函数，供channel回调

    void set_closeCallBack(std::function<void(spConnection)> func);
    void set_errorCallBack(std::function<void(spConnection)> func);
    void set_onMessageCallBack(std::function<void(spConnection, std::string&)> func);
    void set_sendCompleteCallBack(std::function<void(spConnection)> func);
    
    //发送数据，不管在任何线程中，都是调用该函数发送数据
    void send(const char* data, size_t size);
    //发送数据，如果当前线程是IO线程，直接调用此函数，如果是工作线程，将把此函数传给IO线程
    void sendInLoop(const char* data, size_t size);

    bool timeOut(time_t now, int val);   //判断Tcp连接是否超时
};